import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * bigDecimal的常见陷阱
 * @author 16552
 *
 */
public class bigDecimalDemo {
	

	public static void main(String[] args) {
		/**
		 * 陷阱一：BigDecimal实例化精度缺失
		 * 1、由于BigDecimal在实例化对象的时候，new出来的会先将数值转化为一个二进制的值，然后保存在BigDecimal里面
		 * 而一些数值比如说0.01没有一个二进制可以转化，所以jdk会使用一个近似值进行转化
		 * 2、使用valueOf会先将数值转化为Double.toString(val) String类型
		 * 所以我们可以在使用过程中直接使用new BigDecimal("数值")来避免精度问题
		 */
//		BigDecimal bigDecimal1 = new BigDecimal(0.01);
//		BigDecimal bigDecimal2 = BigDecimal.valueOf(0.01);
//		BigDecimal bigDecimal3 = new BigDecimal("12345678456734535675.9543245347543475");
//		System.out.println("bigDecimal1 = " + bigDecimal1);
//		System.out.println("bigDecimal2 = " + bigDecimal2);
//		System.out.println("bigDecimal3 = " + bigDecimal3);
		
		/**
		 * 陷阱二：BigDecimal比较大小
		 * equals:bigDecimal的equals方法重写了Object的equals方法，里面有一个关键代码
		 * if (scale != xDec.scale)
         *   return false;
         * 也就是equals比较了精度，0.01 是两位小数，而0.010是三位小数，故此false
         * 
         * comparesTo:则只比较了大小，所以返回0 （-1小于，0等于，1大于）
		 */
//		BigDecimal bigDecimal1 = new BigDecimal("0.01");
//		BigDecimal bigDecimal2 = new BigDecimal("0.010");
//		System.out.println(bigDecimal1.equals(bigDecimal2));
//		System.out.println(bigDecimal1.compareTo(bigDecimal2));
		
		/**
		 * 陷阱三：BigDecimal计算
		 * bigDecimal在计算的时候，如果计算出来是一个无限小数，则会报错，需要考虑保留的小数位和保留模式
		 */
		BigDecimal bigDecimal1 = new BigDecimal("1");
		BigDecimal bigDecimal2 = new BigDecimal("3");
		//BigDecimal bigDecimal3 = bigDecimal1.divide(bigDecimal2); // 0.3333...
		//System.out.println(bigDecimal3); // Non-terminating decimal expansion; no exact representable decimal result.
		// 上述报错就是无限小数无法精确保存，所以需要考虑四舍五入的保留位数 HALF_UP:四舍五入
		BigDecimal bigDecimal3 = bigDecimal1.divide(bigDecimal2,2,RoundingMode.HALF_UP); // 0.33
		System.out.println(bigDecimal3);
	}
}
